project/cgi-io.git
2 years agomain: fix two one-byte overreads in header_value() master
Jo-Philipp Wich [Wed, 10 Aug 2022 19:43:08 +0000 (21:43 +0200)]
main: fix two one-byte overreads in header_value()

By passing specially crafted header values, the skip loops in the
header_value() function may override the input buffer by one byte
each.

Reported-by: Jinwei Dong <jwdong2000@qq.com>
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
3 years agoRetry splice() syscall on EINTR
Jo-Philipp Wich [Wed, 8 Sep 2021 19:23:49 +0000 (21:23 +0200)]
Retry splice() syscall on EINTR

The invoked child process might end before the I/O loop finished outputting
all data. In such a case, the splice() call might fail with -1/EINTR.

Continue looping in such a case.

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
4 years agotests: add cram based unit tests
Petr Štetiar [Mon, 12 Oct 2020 12:06:11 +0000 (14:06 +0200)]
tests: add cram based unit tests

For the start with cgi-exec testing.

Signed-off-by: Petr Štetiar <ynezz@true.cz>
4 years agotests: add cgi-io built with clang sanitizers
Petr Štetiar [Mon, 12 Oct 2020 12:03:59 +0000 (14:03 +0200)]
tests: add cgi-io built with clang sanitizers

Will be used later for testing.

Signed-off-by: Petr Štetiar <ynezz@true.cz>
4 years agoDisable session ACLs during unit testing
Petr Štetiar [Mon, 12 Oct 2020 11:30:18 +0000 (13:30 +0200)]
Disable session ACLs during unit testing

Otherwise we would need to setup ubus infrastructure etc.

Signed-off-by: Petr Štetiar <ynezz@true.cz>
4 years agoAdd initial GitLab CI support
Petr Štetiar [Sun, 11 Oct 2020 12:12:12 +0000 (14:12 +0200)]
Add initial GitLab CI support

Uses currently proof-of-concept openwrt-ci[1] in order to:

 * improve the quality of the codebase in various areas
 * decrease code review time and help merging contributions faster
 * get automagic feedback loop on various platforms and tools
   - out of tree build with OpenWrt SDK on following targets:
     * ath79-generic
     * imx6-generic
     * malta-be
     * mvebu-cortexa53
   - out of tree native build on x86/64 with GCC (versions 8, 9, 10) and Clang 10
   - out of tree native x86/64 static code analysis with cppcheck and
     scan-build from Clang 10

1. https://gitlab.com/ynezz/openwrt-ci/

Signed-off-by: Petr Štetiar <ynezz@true.cz>
4 years agoAdd .gitignore
Petr Štetiar [Sun, 11 Oct 2020 12:08:42 +0000 (14:08 +0200)]
Add .gitignore

And ignore the `build` dir used by CMake.

Signed-off-by: Petr Štetiar <ynezz@true.cz>
4 years agoFix off-by-one in postdecode_fields
Petr Štetiar [Sun, 11 Oct 2020 11:57:10 +0000 (13:57 +0200)]
Fix off-by-one in postdecode_fields

Fixes following error found by fuzzer:

 ERROR: AddressSanitizer: SEGV on unknown address 0x60c000120000 (pc 0x00000054f64f bp 0x000000000008 sp 0x7ffe4fc2c120 T0)
 The signal is caused by a READ memory access.
    #0 0x54f64f in postdecode_fields cgi-io/util.c:93:7
    #1 0x54f382 in LLVMFuzzerTestOneInput cgi-io/tests/fuzz/test-fuzz.c:36:6

That is caused by reading 1 byte past the size of the buffer.

Signed-off-by: Petr Štetiar <ynezz@true.cz>
4 years agoAdd fuzzing of utility functions
Petr Štetiar [Sun, 11 Oct 2020 11:21:16 +0000 (13:21 +0200)]
Add fuzzing of utility functions

Thus increase fuzzing coverage.

Signed-off-by: Petr Štetiar <ynezz@true.cz>
4 years agoAdd fuzzing of multipart_parser
Petr Štetiar [Sun, 11 Oct 2020 10:46:43 +0000 (12:46 +0200)]
Add fuzzing of multipart_parser

LibFuzzer is in-process, coverage-guided, evolutionary fuzzing engine.

LibFuzzer is linked with the library under test, and feeds fuzzed inputs to
the library via a specific fuzzing entrypoint (aka "target function"); the
fuzzer then tracks which areas of the code are reached, and generates
mutations on the corpus of input data in order to maximize the code coverage.

Lets use libFuzzer to fuzz multipart_parser for the start.

Ref: https://llvm.org/docs/LibFuzzer.html
Signed-off-by: Petr Štetiar <ynezz@true.cz>
4 years agoRefactor utility functions into static library
Petr Štetiar [Sun, 11 Oct 2020 10:43:40 +0000 (12:43 +0200)]
Refactor utility functions into static library

For reusability during testing.

Signed-off-by: Petr Štetiar <ynezz@true.cz>
4 years agoFix clang compiler errors
Petr Štetiar [Sun, 11 Oct 2020 09:04:05 +0000 (11:04 +0200)]
Fix clang compiler errors

Fixes following errors as reported by clang compilers:

 cgi-io/src/main.c:723:12: error: unused variable 'post' [-Werror,-Wunused-variable]
         autochar *post = postdecode(fields, 4);
                  ^
 cgi-io/src/main.c:814:12: error: unused variable 'post' [-Werror,-Wunused-variable]
         autochar *post = postdecode(fields, 1);
                  ^
 cgi-io/src/main.c:996:12: error: unused variable 'post' [-Werror,-Wunused-variable]
         autochar *post = postdecode(fields, 4);

Signed-off-by: Petr Štetiar <ynezz@true.cz>
4 years agoFix possible NULL dereference
Petr Štetiar [Sun, 11 Oct 2020 08:56:24 +0000 (10:56 +0200)]
Fix possible NULL dereference

Fixes following issue as reported by GCC-10 static analyzer:

 multipart_parser.c: In function ‘multipart_parser_init’:
 multipart_parser.c:88:22: error: dereference of possibly-NULL ‘p’ [CWE-690] [-Werror=analyzer-possible-null-dereference]

   88 |   p->boundary_length = strlen(boundary);
      |   ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
  ‘multipart_parser_init’: events 1-2
    |
    |   83 |   multipart_parser* p = malloc(sizeof(multipart_parser) +
    |      |   ^~~~~~~~~~~~~~~~
    |      |   |
    |      |   (1) this call could return NULL
    |......
    |   88 |   p->boundary_length = strlen(boundary);
    |      |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    |      |                      |
    |      |                      (2) ‘p’ could be NULL: unchecked value from (1)

Signed-off-by: Petr Štetiar <ynezz@true.cz>
4 years agoFix warnings reported by clang-10 static analyzer
Petr Štetiar [Sun, 11 Oct 2020 08:45:15 +0000 (10:45 +0200)]
Fix warnings reported by clang-10 static analyzer

Fixes following warnings:

 testing/include/libubox/blobmsg.h:222:67: warning: Null pointer passed to 1st parameter expecting 'nonnull'
         return blobmsg_add_field(buf, BLOBMSG_TYPE_STRING, name, string, strlen(string) + 1);
                                                                         ^~~~~~~~~~~~~~
 cgi-io/main.c:407:4: warning: Null pointer passed to 1st parameter expecting 'nonnull'
                         unlink(st.filename);
                         ^~~~~~~~~~~~~~~~~~~

 cgi-io/main.c:876:26: warning: Null pointer passed to 1st parameter expecting 'nonnull'
         size_t plen = 0, clen = strlen(cmd) + 1;
                                 ^~~~~~~~~~~

Signed-off-by: Petr Štetiar <ynezz@true.cz>
4 years agoRemove Makefile
Petr Štetiar [Sun, 11 Oct 2020 12:47:43 +0000 (14:47 +0200)]
Remove Makefile

It makes no sense to keep it as the project now lives as a separate C
project.

Signed-off-by: Petr Štetiar <ynezz@true.cz>
4 years agoRemove src subdir
Petr Štetiar [Sun, 11 Oct 2020 12:47:43 +0000 (14:47 +0200)]
Remove src subdir

It makes no sense now as the project now lives as a separate C project.

Signed-off-by: Petr Štetiar <ynezz@true.cz>
4 years agocgi-io: fix compilation against uClibc
Jo-Philipp Wich [Thu, 27 Feb 2020 11:38:15 +0000 (12:38 +0100)]
cgi-io: fix compilation against uClibc

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
4 years agocgi-io: use O_TMPFILE for uploads and attempt to directly link target file
Jo-Philipp Wich [Fri, 21 Feb 2020 23:13:32 +0000 (00:13 +0100)]
cgi-io: use O_TMPFILE for uploads and attempt to directly link target file

Create an anonymous inode in /tmp using O_TMPFILE and attempt to link the
file in place using linkat(). Only fall back to the old file copy when
linking the tempfile fails.

Avoids double memory use if both the temporary upload file and the
destination file are located in /tmp.

Ref: https://github.com/openwrt/luci/issues/3654
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
4 years agocgi-io: use dynamic memory for post decoding, support proc files
Jo-Philipp Wich [Mon, 10 Feb 2020 17:19:34 +0000 (18:19 +0100)]
cgi-io: use dynamic memory for post decoding, support proc files

Allocate dynamic buffer memory for decoding post data and allow post
requsts up to 128KB compared to the previos 1KB limit.

Also support downloading /proc and /sys files by falling back to
chunked transfer encoding when the file size cannot be determined.

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
4 years agocgi-io: close pipe descriptors early
Jo-Philipp Wich [Wed, 18 Dec 2019 08:32:38 +0000 (09:32 +0100)]
cgi-io: close pipe descriptors early

In the command read side, close the superfluous write end of the pipe
early to ensure that EOF is reliably detected. Without that change, splice
calls to read from the pipe will occasionally hang until the CGI process
is eventually killed due to timeout.

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
4 years agocgi-io: implement exec action
Jo-Philipp Wich [Fri, 13 Dec 2019 08:08:51 +0000 (09:08 +0100)]
cgi-io: implement exec action

Implement a new "cgi-exec" applet which allows to invoke remote commands
and stream their stdandard output back to the client via HTTP. This is
needed in cases where large amounts of data or binary encoded contents
such as tar archives need to be transferred, which are unsuitable to be
transported via ubus directly.

The exec call is guarded by the same ACL semantics as rpcd's file plugin,
means in order to be able to execute a command remotely, the ubus session
identified by the given session ID must have read access to the "exec"
function of the "cgi-io" scope and an explicit "exec" permission rule for
the invoked command in the "file" scope.

In order to initiate a transfer, a POST request in x-www-form-urlencoded
format must be sent to the applet, with one field "sessionid" holding
the login session and another field "command" specifiying the commandline
to invoke.

Further optional fields are "filename" which - if present - will cause
the download applet to set a Content-Dispostition header and "mimetype"
which allows to let the applet respond with a specific type instead of
the default "application/octet-stream".

Below is an example for the required ACL rules to grant exec access to
both the "date" and "iptables" commands. The "date" rule specifies the
base name of the executable and thus allows invocation with arbitrary
parameters while the latter "iptables" rule merely allows one specific
set of arguments which must appear exactly in the given order.

    ubus call session grant '{
        "ubus_rpc_session": "...",
        "scope": "cgi-io",
        "objects": [
            [ "exec", "read" ]
        ]
    }'

    ubus call session grant '{
        "ubus_rpc_session": "...",
        "scope": "file",
        "objects": [
            [ "/bin/date", "exec" ],
            [ "/usr/sbin/iptables -n -v -L", "exec" ]
        ]
   }'

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
5 years agocgi-io: iron out extra compiler warnings
Petr Štetiar [Fri, 11 Oct 2019 13:07:17 +0000 (15:07 +0200)]
cgi-io: iron out extra compiler warnings

Fixes following errors:

 main.c:458:37: error: comparison of integer expressions of different signedness: ‘int’ and ‘size_t’ {aka ‘long unsigned int’} [-Werror=sign-compare]
 main.c:463:17: error: comparison of integer expressions of different signedness: ‘int’ and ‘long unsigned int’ [-Werror=sign-compare]
 main.c:518:35: error: comparison of integer expressions of different signedness: ‘ssize_t’ {aka ‘long int’} and ‘size_t’ {aka ‘long unsigned int’} [-Werror=sign-compare]
 main.c:157:3: error: ignoring return value of ‘read’, declared with attribute warn_unused_result [-Werror=unused-result]
 main.c:763:3: error: ignoring return value of ‘chdir’, declared with attribute warn_unused_result [-Werror=unused-result]

Signed-off-by: Petr Štetiar <ynezz@true.cz>
5 years agocgi-io: cmake: enable extra compiler warnings
Petr Štetiar [Fri, 11 Oct 2019 13:03:04 +0000 (15:03 +0200)]
cgi-io: cmake: enable extra compiler warnings

Spotting issues during compilation is cheaper.

Signed-off-by: Petr Štetiar <ynezz@true.cz>
5 years agocgi-io: cmake: fix libraries lookup
Petr Štetiar [Fri, 11 Oct 2019 13:01:42 +0000 (15:01 +0200)]
cgi-io: cmake: fix libraries lookup

In order to make it compile properly in more environments.

Signed-off-by: Petr Štetiar <ynezz@true.cz>
5 years agocgi-io: fix read after end errors
Ansuel Smith [Tue, 8 Oct 2019 20:34:11 +0000 (22:34 +0200)]
cgi-io: fix read after end errors

Currently cgi-io try to read data after the data ended.
- Adds "-" to whitelist char
- In main_upload is tried to consume the buffer while it's already readed by the while loop before

Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
5 years agocgi-io: use splice() to stream backup archive
Jo-Philipp Wich [Fri, 13 Sep 2019 07:17:58 +0000 (09:17 +0200)]
cgi-io: use splice() to stream backup archive

This improves the I/O performance when outputting large backups.

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
5 years agocgi-io: pass appropriate HTTP error codes to failure()
Jo-Philipp Wich [Fri, 13 Sep 2019 06:32:58 +0000 (08:32 +0200)]
cgi-io: pass appropriate HTTP error codes to failure()

Instead of always replying with a generic 500 internal server error code,
use more appropriate codes such as 403 to indicate denied permissions.

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
5 years agocgi-io: add download operation
Jo-Philipp Wich [Fri, 13 Sep 2019 05:23:25 +0000 (07:23 +0200)]
cgi-io: add download operation

Add a new `cgi-download` applet which allows to retrieve the contents
of regular files or block devices.

In order to initiate a transfer, a POST request in x-www-form-urlencoded
format must be sent to the applet, with one field "sessionid" holding
the login session and another field "path" containing the file path to
download.

Further optional fields are "filename" which - if present - will cause
the download applet to set a Content-Dispostition header and "mimetype"
which allows to let the applet respond with a specific type instead of
the default "application/octet-stream".

Below is an example for the required acl rules to grant download access
to files or block devices:

    ubus call session grant '{
        "ubus_rpc_session": "...",
        "scope": "cgi-io",
        "objects": [
            [ "download", "read" ]
        ]
    }'

    ubus call session grant '{
        "ubus_rpc_session": "...",
        "scope": "file",
        "objects": [
            [ "/etc/config/*", "read" ],
            [ "/dev/mtdblock*", "read" ]
        ]
    }'

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
5 years agocgi-io: use different acl scopes for path and command permissions
Jo-Philipp Wich [Fri, 13 Sep 2019 04:52:21 +0000 (06:52 +0200)]
cgi-io: use different acl scopes for path and command permissions

Use the `cgi-io` scope to check for permission to execute the requested
command (`upload`, `backup`) and the `file` scope to check path
permissions.

The reasoning of this change is that `cgi-io` is usually used in
conjunction with `rpcd-mod-file` to transfer large file data out
of band and `rpcd-mod-file` already uses the `file` scope to manage
file path access permissions. After this change, both `rpc-mod-file`
and `cgi-io` can share the same path acl rules.

Write access to a path can be granted by using an ubus call in the
following form:

    ubus call session grant '{
        "ubus_rpc_session": "...",
        "scope": "file",
        "objects": [
            [ "/var/lib/uploads/*", "write" ]
        ]
    }'

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
5 years agotreewide: Change .*GPL.*+ licenses to SPDX compatible identifier
Sven Eckelmann [Mon, 2 Sep 2019 13:15:08 +0000 (15:15 +0200)]
treewide: Change .*GPL.*+ licenses to SPDX compatible identifier

The CONTRIBUTING.md requests an (or multiple) SPDX identifier for GPL
licenses. But a lot of packages did use a different, non-SPDX style with a
"+" at the end instead of "-or-later".

Signed-off-by: Sven Eckelmann <sven@narfation.org>
5 years agocgi-io: require whitelisting upload locations
Jo-Philipp Wich [Fri, 30 Aug 2019 05:50:43 +0000 (07:50 +0200)]
cgi-io: require whitelisting upload locations

Introduce further ACL checks to verify that the request-supplied
upload location may be written to. This prevents overwriting things
like /bin/busybox and allows to confine uploads to specific directories.

To setup the required ACLs, the following ubus command may be used
on the command line:

ubus call session grant '{
  "ubus_rpc_session": "d41d8cd98f00b204e9800998ecf8427e",
  "scope": "cgi-io",
  "objects": [
    [ "/etc/certificates/*", "write" ],
    [ "/var/uploads/*", "write" ]
  ]
}'

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
5 years agocgi-io: Fix bug
Jianhui Zhao [Thu, 30 May 2019 02:03:29 +0000 (10:03 +0800)]
cgi-io: Fix bug

The installation name is inconsistent with the code

Signed-off-by: Jianhui Zhao <jianhuizhao329@gmail.com>
7 years agocgi-io: support SHA256 checksums for file uploads
Jo-Philipp Wich [Mon, 13 Nov 2017 16:00:58 +0000 (17:00 +0100)]
cgi-io: support SHA256 checksums for file uploads

Report SHA256 checksums in addition to the MD5 ones to make cgi-io suitable
for sysupgrade image verification.

Also allow stat(), md5sum and/or sha256sum to fail and respond with a JSON
null value instead, leaving it to the frontend to handle errors as needed.

Fixes #4790.

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
7 years agocgi-io: fix stray semicolon
Jo-Philipp Wich [Fri, 18 Aug 2017 12:28:33 +0000 (14:28 +0200)]
cgi-io: fix stray semicolon

Remove an improperly placed semicolon in order to solve the following
compiler error:

.../main.c:144:3: error: this 'if' clause does not guard... [-Werror=misleading-indentation]
    if (execl("/bin/busybox", "/bin/busybox", "md5sum", file, NULL));
    ^~
    .../main.c:145:4: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
    return NULL;
    ^~~~~~
    cc1: all warnings being treated as errors

Fixes #4723.

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
7 years agocgi-io: merge changes from luci2-io-helper
Daniel Golle [Mon, 19 Jun 2017 10:48:32 +0000 (12:48 +0200)]
cgi-io: merge changes from luci2-io-helper

luci2-io-helper: bugfix buckup script read timeout

Reading files from stdin will block for ever. The uhttpd is killing the
backup process after script_timeout.

Switching read to non blocking mode and add a waitpid for the slave
process does not end in a script_timeout anymore.

Signed-off-by: Florian Eckert <Eckert.Florian@googlemail.com>
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
7 years agocgi-io: Find and search for libubus.h
Florian Fainelli [Sun, 18 Jun 2017 19:45:30 +0000 (12:45 -0700)]
cgi-io: Find and search for libubus.h

Fixes build errors with external toolchains:

[ 33%] Building C object CMakeFiles/cgi-io.dir/main.c.o
/home/florian/dev/openwrt/trunk/build_dir/target-mipsel-unknown-linux-gnu_glibc/cgi-io/main.c:30:21:
fatal error: libubus.h: No such file or directory
 #include <libubus.h>
                     ^
compilation terminated.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
8 years agotreewide: replace my defunct email address
Jo-Philipp Wich [Tue, 7 Jun 2016 10:00:01 +0000 (12:00 +0200)]
treewide: replace my defunct email address

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
9 years agocgi-io: add a small helper cgi that can be used by RPCD based UIs
John Crispin [Thu, 1 Oct 2015 15:34:13 +0000 (17:34 +0200)]
cgi-io: add a small helper cgi that can be used by RPCD based UIs

Signed-off-by: John Crispin <blogic@openwrt.org>